/*-------------------------------------------------------------------------*/
/**
  @file		mpiloop.c
  @author	Renaud Wanschoor
  @date	july 2004
  @version	$Revision: 2.6 $
  @brief	parallel runs of pagrid

  intend to implement a program that is able to run multiple runs
  of a partitioning tool in parallel, it is not finished and it is not
  working.

*/
/*--------------------------------------------------------------------------*/

#ifdef MPI
#include "mpi.h"
#endif
#include "plib.h"

#define INPUT_FILE "./mpiloop.cfg"
#define JOB_SIZE   100

typedef struct job{
  int size;
  char cmd[MAXLINE];  
}job;

int readcfg(char* F_in,int* my_nb_jobs,job** my_jobs);
int printjobs(job* jobs, int size);
int runcmd(char* mycmd);

int main(int argc, char *argv[]){
#ifdef MPI
  MPI_Status status;
  MPI_Comm comm=MPI_COMM_WORLD;
  int masterid,myrank,mysize;
  char flag;
  char end[MAXLINE];    
  char cmd[MAXLINE];
#endif
  int i;
  job* jobs;
  int nb_jobs = 0;  

  /*Initialize MPI*/
#ifdef MPI
  masterid=0;
  MPI_Init(&argc,&argv);
  MPI_Comm_size(comm,&mysize);
  MPI_Comm_rank(comm,&myrank);
#endif  

#ifdef MPI
  getcwd(cwd,MAXLINE);
  NOTICE((1,"1 myrank %d/%d %s\n",myrank,mysize,cwd));
  /* read experiments */

  if(myrank == masterid){    
    NOTICE((1,"2 myrank %d/%d",myrank,mysize));
#endif
    readcfg(INPUT_FILE,&nb_jobs,&jobs);
#ifdef MPI
    NOTICE((1,"3 myrank %d/%d",myrank,mysize));
#endif
    /*printjobs(jobs, nb_jobs);*/
#ifdef MPI
  }
#endif

#ifdef MPI
  if(myrank == masterid){
    strcpy(end,"%%END%%");
    NOTICE((1,"[%d] begin",myrank));
    for(i=0;i<nb_jobs;i++){
      NOTICE((1,"[%d] job %d\n",myrank,i));
      while(jobs[i].size){
	NOTICE((1,"[%d] remain %d",myrank, jobs[i].size));
	NOTICE((1,"[%d] wait slave\n",myrank));
	MPI_Recv(&flag,1,MPI_CHAR,MPI_ANY_SOURCE,1,comm,&status);
	NOTICE((1,"[%d] recv signal from %d\n",myrank,status.MPI_SOURCE));
	MPI_Send(jobs[i].cmd,MAXLINE,MPI_CHAR,status.MPI_SOURCE,1,comm);
	NOTICE((1,"[%d] sent cmd to %d\n",myrank,status.MPI_SOURCE));
	jobs[i].size--;
      }
    }
    for(i=0;i<mysize;i++){
      NOTICE((1,"[%d] wait slave\n",myrank));
      MPI_Recv(&flag,1,MPI_CHAR,MPI_ANY_SOURCE,1,comm,&status);
      NOTICE((1,"[%d] recv signal from %d\n",myrank,status.MPI_SOURCE));
      MPI_Send(&end,MAXLINE,MPI_CHAR,status.MPI_SOURCE,1,comm);
      NOTICE((1,"[%d] sent end to %d\n",myrank,status.MPI_SOURCE));
    }
  }else{    
    strcpy(cmd,"");
    for(;;){
      NOTICE((1,"[%d] sending signal to %d\n",myrank,masterid));
      MPI_Send(&flag,1,MPI_CHAR,masterid,1,comm);
      NOTICE((1,"[%d] sent signal to %d\n",myrank,masterid));	
      MPI_Recv(cmd,MAXLINE,MPI_CHAR,masterid,1,comm,&status);
      printf("recv cmd from %d\n",masterid);
      if(strcmp(cmd,"%%END%%") == 0){
	 printf("recv end %d\n",myrank);
	break;
      }
      runcmd(cmd);
    }
  }
#else
  for(i=0;i<nb_jobs;i++){
    printf("\nrunning : %s\n",jobs[i].cmd);
    while(jobs[i].size){
      printf("%d ",jobs[i].size);fflush(stdout);      
      runcmd(jobs[i].cmd);
      jobs[i].size--;
    }
  }
#endif  

#ifdef MPI
  /*Clean up MPI then exit*/
  MPI_Finalize();
#endif

  return 0;
}

int runcmd(char* mycmd){
  int i;
  FILE* fp;
  char F_match[MAXLINE];
  char cmd[MAXLINE];
  
  if(mycmd[strlen(mycmd)-1] == 'S'){
    for(i=1;;i++){
      sprintf(F_match,"matching.%d.%s",i,IO_FSER);
      if((fp=fopen(F_match,"r")) == NULL || fclose(fp) == EOF){
	break;
      }
      sprintf(cmd,"%s %s",mycmd,F_match);
      ERROR((system(cmd)!=0,"error running comand %s\n",cmd));
    }
    return 1;
  }

  ERROR((system(mycmd)!=0,"error running comand %s\n",cmd));
  return 1;
}

int readcfg(char* F_in,int* my_nb_jobs,job** my_jobs){
  FILE* fp;
  char line[MAXLINE];
  int nb_jobs = 0;
  job* jobs = U_malloc(JOB_SIZE,job,"readcfg malloc error 1\n");
  int jobs_size = JOB_SIZE;
  char *tok;
  int linenb = 0;

  WARNING(((fp = fopen(F_in,"r")) == NULL,"cannot read %s\n",F_in),0);
  
  do{
    do { 
      fgets(line, MAXLINE, fp);
      linenb++;
    } while ((line[0] == '%' || strcmp(line,"\n")==0) && !feof(fp));

    if(feof(fp))
      break;

    nb_jobs++;     

    if(nb_jobs > jobs_size){
      U_realloc(jobs,jobs_size*2,job,"readcfg realloc error 1\n");
      jobs_size*=2;
    }
    
    WARNING(((tok = strtok(line," ")) == NULL,"readcfg cannot read experiments number line %d\n",linenb),0);
    
    jobs[nb_jobs-1].size = atoi(tok);

    WARNING(((tok = strtok(NULL,"\n")) == NULL,"readcfg cannot read command line %d\n",linenb),0);
        
    strcpy(jobs[nb_jobs-1].cmd,tok);
    
  }while(!feof(fp));

  fclose(fp);

  *my_jobs = jobs;
  *my_nb_jobs = nb_jobs;

  return 1;
}

int printjobs(job* jobs, int size){
  int i;
  for(i=0;i<size;i++){
    printf("job %3d\n",i);
    printf("-------\n");
    printf("cmd  : %s\n",jobs[i].cmd);    
    printf("size : %d\n\n",jobs[i].size);    
  }
  return 1;
}
